package com.yike.product.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yike.common.api.BarcodeApiResult;
import com.yike.common.base.BaseServiceImpl;
import com.yike.common.enums.GoodsCodeEnum;
import com.yike.common.exception.BusinessException;
import com.yike.common.exception.GoodsBusinessException;
import com.yike.common.pagination.Paging;
import com.yike.common.pagination.PageInfo;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yike.common.tool.LoginUtil;
import com.yike.common.vo.MachineVo;
import com.yike.product.client.BarcodeApiClient;
import com.yike.product.convert.BarcodeConvert;
import com.yike.product.convert.GoodsConvert;
import com.yike.product.convert.GoodsCustomConvert;
import com.yike.product.entity.Barcode;
import com.yike.product.entity.Category;
import com.yike.product.entity.Goods;
import com.yike.product.entity.GoodsPriceRecord;
import com.yike.product.mapper.CategoryMapper;
import com.yike.product.mapper.GoodsMapper;
import com.yike.product.mapper.GoodsPriceRecordMapper;
import com.yike.product.param.*;
import com.yike.product.service.BarcodeService;
import com.yike.product.service.GoodsService;
import com.yike.product.service.SpecificationService;
import com.yike.product.vo.*;
import com.yike.user.api.service.ShopFeignService;
import com.yike.user.api.service.UserFeignService;
import com.yike.user.api.vo.ShopFeignVo;
import com.yike.user.api.vo.UserVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 商品表 服务实现类
 *
 * @author yike
 * @since 2024-07-17
 */
@Slf4j
@Service
public class GoodsServiceImpl extends BaseServiceImpl<GoodsMapper, Goods> implements GoodsService {

    @Resource
    private GoodsMapper goodsMapper;

    @Autowired
    private BarcodeService barcodeService;

    @Resource
    private UserFeignService userFeignService;

    @Resource
    private BarcodeApiClient barcodeApiClient;

    @Autowired
    private SpecificationService specificationService;

    @Resource
    private ShopFeignService shopFeignService;

    @Autowired
    private CategoryMapper categoryMapper;

    @Autowired
    private GoodsPriceRecordMapper goodsPriceRecordMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean saveGoods(AddGoodsParam addGoodsParam) {
        Wrapper wrapper = Wrappers.lambdaQuery(Goods.class).eq(Goods::getBarcode, addGoodsParam.getBarcode());
        Goods dbGoods = goodsMapper.selectOne(wrapper);
        if (ObjectUtil.isNotNull(dbGoods)) {
            throw new BusinessException(GoodsCodeEnum.BARCODE_IS_EXSIT);
        }
        //保存自定义规格
        specificationService.save(addGoodsParam.getSpecification());
        //新增物品
        Goods goods = GoodsConvert.INSTANCE.convert(addGoodsParam);
        goods.setCreateBy(LoginUtil.getUserId());
        return super.save(goods);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateGoods(UpdateGoodsParam updateGoodsParam) throws Exception {
        Goods dbGoods = goodsMapper.selectById(updateGoodsParam.getId());
        if (ObjectUtil.isNull(dbGoods)) {
            new BusinessException(GoodsCodeEnum.GOODS_NO_EXSIT);
        }
        // 判断商品价格是否发送改变，如果改变则添加一条记录
        if (dbGoods.getSellPrice().compareTo(updateGoodsParam.getSellPrice()) != 0) {
            // 获取店铺信息
            ShopFeignVo shopFeignVo = shopFeignService.getShop(dbGoods.getShopId());
            if (shopFeignVo == null) {
                throw new BusinessException("店铺信息异常，请联系工作人员");
            }
            GoodsPriceRecord goodsPriceRecord = new GoodsPriceRecord();
            goodsPriceRecord.setShopId(dbGoods.getShopId());
            goodsPriceRecord.setShopName(shopFeignVo.getShopName());
            goodsPriceRecord.setGoodsId(updateGoodsParam.getId());
            goodsPriceRecord.setGoodsName(updateGoodsParam.getName());
            goodsPriceRecord.setSpecification(updateGoodsParam.getSpecification());
            goodsPriceRecord.setSellPrice(updateGoodsParam.getSellPrice());
            goodsPriceRecord.setBuyPrice(updateGoodsParam.getBuyPrice());
            goodsPriceRecord.setCreateBy(LoginUtil.getUserId());
            goodsPriceRecordMapper.insert(goodsPriceRecord);
        }
        Goods goods = GoodsConvert.INSTANCE.convert(updateGoodsParam);
        goods.setUpdateBy(LoginUtil.getUserId());
        return super.updateById(goods);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteGoods(Long id) throws Exception {
        return super.removeById(id);
    }

    @Override
    public Paging<GoodsVo> getGoodsPageList(GoodsPageParam param) throws Exception {
        //查询条件
        LambdaQueryWrapper<Goods> wrapper = new LambdaQueryWrapper<>();
        boolean searchFlag = StrUtil.isNotBlank(param.getSearchValue());
        wrapper.eq(Goods::getShopId, LoginUtil.getShopId())
                .and(searchFlag, w -> w.like(Goods::getBarcode, param.getSearchValue())
                        .or()
                        .like(Goods::getName, param.getSearchValue()));
        //分页对象
        Page<Goods> page = new PageInfo<>(param);
        //分页查询
        IPage<Goods> iPage = goodsMapper.selectPage(page, wrapper);
        List<GoodsVo> goodsVos = GoodsConvert.INSTANCE.convert(iPage.getRecords());
        //拼接人员信息
        if (CollectionUtil.isNotEmpty(goodsVos)) {
            Set<Long> userIds = new HashSet<>();
            goodsVos.forEach(a -> {
                userIds.add(a.getCreateBy());
                userIds.add(a.getUpdateBy());
            });
            List<UserVo> userVos = userFeignService.list(userIds);
            Map<Long, String> listMap = userVos.stream().collect(Collectors.toMap(UserVo::getId, UserVo::getUsername));
            goodsVos.forEach(a -> {
                a.setCreateByName(listMap.get(a.getCreateBy()));
                a.setUpdateByName(listMap.get(a.getUpdateBy()));
            });
        }
        //返回列表对象
        return new Paging(iPage, goodsVos);
    }

    @Override
    public GoodsCustomVo getByBarcode(String barcode) {
        MachineVo machineVo = LoginUtil.getMachineVo();
        Wrapper wrapper = Wrappers.lambdaQuery(Goods.class).eq(Goods::getBarcode, barcode).eq(Goods::getShopId, machineVo.getShopId());
        Goods goods = goodsMapper.selectOne(wrapper);
        GoodsCustomVo vo = GoodsConvert.INSTANCE.convert(goods);
        if (ObjectUtil.isNull(vo)) {
            throw new BusinessException(GoodsCodeEnum.BARCODE_NO_STORE);
        }

        // 客户端扫码的时候需要判断当前店铺是否开启了一键调价
        ShopFeignVo shopFeignVo = shopFeignService.getShop(machineVo.getShopId());
        if (shopFeignVo == null) {
            throw new BusinessException("店铺信息异常，请联系工作人员");
        }
        // 如果开启了调价那么当前所有商品价格都需要上涨
        if (shopFeignVo.getAdjustPriceFlag()) {
            // 将调价百分比转为 1.xx 格式，比如 10% 就是 1.10
            BigDecimal adjustmentFactor = BigDecimal.valueOf(1).add(BigDecimal.valueOf(shopFeignVo.getAdjustPriceRate()).divide(BigDecimal.valueOf(100)));
            // 计算调价后的新价格，并保留两位小数
            BigDecimal adjustedPrice = vo.getPrice().multiply(adjustmentFactor).setScale(2, RoundingMode.HALF_UP);
            // 设置新的价格
            vo.setPrice(adjustedPrice);
        }

        return vo;
    }

    @Override
    public GoodsVo getGoods(Long id) {
        Goods goods = goodsMapper.selectById(id);
        if (goods == null) {
            throw new BusinessException(GoodsCodeEnum.GOODS_NO_EXSIT);
        }
        GoodsVo goodsVo = new GoodsVo();
        BeanUtils.copyProperties(goods, goodsVo);
        // 获取创建人和修改人信息
        UserVo createUser = userFeignService.getUserById(goods.getCreateBy());
        if (createUser != null) {
            goodsVo.setCreateByName(createUser.getNickname());
        }
        UserVo updateUser = userFeignService.getUserById(goods.getUpdateBy());
        if (updateUser != null) {
            goodsVo.setUpdateByName(updateUser.getNickname());
        }
        // 获取类型名称
        Category category = categoryMapper.selectById(goods.getCategoryId());
        if (category != null) {
            goodsVo.setCategoryName(category.getName());
        }
        return goodsVo;
    }

    @Override
    public GoodsShopVo getByBarcodeForShop(String barcode) throws Exception {
        Wrapper wrapper = Wrappers.lambdaQuery(Goods.class).eq(Goods::getBarcode, barcode).eq(Goods::getShopId, LoginUtil.getShopId());
        Goods goods = goodsMapper.selectOne(wrapper);
        if (ObjectUtil.isNotNull(goods)) {
            throw new GoodsBusinessException(GoodsCodeEnum.GOODS_IS_EXSIT);
        }
        wrapper = Wrappers.lambdaQuery(Barcode.class).eq(Barcode::getCode, barcode);
        Barcode dbBarcode = barcodeService.getOne(wrapper);

        if (ObjectUtil.isNotNull(dbBarcode)) {
            return BarcodeConvert.INSTANCE.convert(dbBarcode);
        }

        BarcodeApiResult<GoodsBarcodeApiVo> barcodeApiResult = barcodeApiClient.querybarcode(barcode);
        GoodsBarcodeApiVo goodsBarcodeApiVo = barcodeApiResult.getResult();
        if (ObjectUtil.isNotNull(goodsBarcodeApiVo)) {
            Barcode barcodeResult = BarcodeConvert.INSTANCE.convert(goodsBarcodeApiVo);
            barcodeResult.setCreateBy(LoginUtil.getUserId());
            barcodeService.saveBarcode(barcodeResult);
            return BarcodeConvert.INSTANCE.convert(barcodeResult);
        } else {
            throw new BusinessException(GoodsCodeEnum.GOODS_NO_FIND);
        }
    }

    @Override
    public Paging<GoodsCustomVo> getGoodsCustomPageList(GoodsCustomPageParam param) {
        //查询条件
        MachineVo machineVo = LoginUtil.getMachineVo();
        LambdaQueryWrapper<Goods> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StrUtil.isNotBlank(param.getBarcode()), Goods::getBarcode, param.getBarcode())
                .eq(Goods::getShopId, machineVo.getShopId());
        //分页对象
        Page<Goods> page = new PageInfo<>(param);
        IPage<Goods> iPage = goodsMapper.selectPage(page, wrapper);
        List<GoodsCustomVo> goodsVos = GoodsCustomConvert.INSTANCE.convert(iPage.getRecords());
        return new Paging(iPage, goodsVos);
    }

    @Override
    public Paging<GoodsListVo> getShopGoodsList(ShopGoodsPageParam shopGoodsPageParam) throws Exception {
        Page<Goods> page = new PageInfo<>(shopGoodsPageParam);
        if (shopGoodsPageParam.getShopId() == null) {
            shopGoodsPageParam.setShopId(LoginUtil.getShopId());
        }
        IPage<GoodsListVo> iPage = goodsMapper.getShopGoodsList(page, shopGoodsPageParam);
        return new Paging<GoodsListVo>(iPage);
    }

    @Override
    public List<String> getShopGoodsSearchData(String keyword) throws Exception {
        return goodsMapper.getShopGoodsSearchData(LoginUtil.getShopId(), keyword);
    }


}
